/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package trojkatyR;

import gra.TVisualisation;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.vecmath.Point3d;
import out.IOut;
import out.TOut1_2;
import ste.TAbstBlock;
import trojkaty.Tri;
import wej.TDaneWej;

/**
 *
 * @author arkadiusz
 */
public class TrojkatyR extends TAbstBlock{
    
    private ArrayList<Point3d[]> fPtTAL = new ArrayList<Point3d[]>();
    private JComponent panel = new PanelTrojkaty(this);
    private double theDist; //odleglosc pomiedzy trojkatami
    private ArrayList<Tri> theTriAL = new ArrayList<Tri>(); //lista trojkatow

    @Override
    public String getTabTitle() {
        return "Wieksze trojkaty";
    }

    @Override
    public JComponent getJComponent() { return panel;   }

    @Override
    public void setNext(TAbstBlock aNext) { theNext = aNext; }

    @Override
    public void checkSettings() {
        theDist = 0.02d; //m. (pobrac parametr z okna.....)panel.get
        theNext.checkSettings();
    } //koniec checkSettings

    @Override
    public void showGraphic() {
        TVisualisation _lVis = new TVisualisation(); //do grafiki
        _lVis.addTriangleT(theTriAL.toArray(new Tri[theTriAL.size()]));
        _lVis.display();
    } //koniec showGraphic

    @Override
    public void clear() {
        fPtTAL.clear();
        theTriAL.clear();
        theNext.clear();
    } //koniec clear

    @Override
    public void starter(IOut o) {
        if (!(o instanceof TOut1_2)) return;
        TOut1_2 in = (TOut1_2) o;
        
        //Tworze tablice obiektow z jednego skanu2D
        Point3d[] ptRT = new Point3d[in.getXT().length];
        
        for (int i=0; i<ptRT.length; i++)
            ptRT[i] = new Point3d(in.getXT()[i], in.getYT()[i], in.getZT()[i]);
        
        fPtTAL.add(ptRT); //dodaje caly skan2D, jako jeden obiekt
        theNext.starter(o);
    } //koniec starter

    @Override
    public void finish() {
        //Tworze trojkat dla kazdego pktu osobno
        for (int i=0; i<fPtTAL.size(); i++) {//biorę skan2D
            Point3d[] p3T = fPtTAL.get(i);
            for (int j=0; j<p3T.length; j++) {//biorę każdy pkt ze skanu
                createTrojkat(p3T, i, j); //tworzę trojkat dla danego pktu
            } //koniec for j
        } //koniec for i
        theNext.finish();
    } //koniec finish

    private void createTrojkat(Point3d[] aPtT, int aPionNo, int aPozNo) {

        //1. Biore skan2D z tego pktu
        Point3d pA = new Point3d(aPtT[aPozNo]);

        Point3d pB=null, pC=null; //punkty do trojkata, wzdluz osi OX i OZ;        
        Point3d pD=null, pE=null; //punkty do trojkata, wzdluz osi OX i OZ;  
        
        //2. Szukam najbliższego pktu nie większego niż theDist (na plnie XY);
        for (int i=aPozNo+1; i<aPtT.length; i++) {
            if (getDistXY(aPtT[i], pA) > theDist) {
                pB = aPtT[i-1];
                break;
            } //koniec if
        } //koniec for
        
        //2a. To samo co wyżej, ale w prawo a nie w lewo
        for (int i=aPozNo; i>0; i--) {
            if (getDistXY(aPtT[i], pA) > theDist) {
                pD = aPtT[i+1];
                break;
            } //koniec if
        } //koniec for
        
        //3. Szukam najblizszego pktu NIE wiekszego niz theDist (wzdluz osi Z)
        for (int i=aPionNo+1; i<fPtTAL.size(); i++) {
            if (getDistZ(fPtTAL.get(i)[aPozNo], pA) > theDist) {
                pC = fPtTAL.get(i-1)[aPozNo];  
                break;
            } //koniec if
        } //koniec for
        
        //3a. To samo co wyżej, ale w dol a nie w gore
        for (int i=aPionNo; i>0; i--) {
            if (getDistZ(fPtTAL.get(i)[aPozNo], pA) > theDist) {
                pE = fPtTAL.get(i+1)[aPozNo];  
                break;
            } //koniec if
        } //koniec for
        
        if (pA!=null && pB!=null && pC!=null) //cz. jest trojkat i moge go rysowac
             addTrojkat(theTriAL, pA, pB, pC);
        if (pA!=null && pD!=null && pE!=null) //cz. jest trojkat i moge go rysowac
             addTrojkat(theTriAL, pA, pD, pE);
    } //koniec createTrojkat
    
    //Zwraca odleglosc pomiedzy pktami w plnie XY (bez osi Z)
    private double getDistXY(Point3d aPt1, Point3d aPt2) {
        return Math.abs(Math.pow(aPt2.x-aPt1.x, 2)+Math.pow(aPt2.y-aPt1.y, 2));
    } //koniec getDistXY
    
    //Zwraca odleglosc pomiedzy pktami w osi Z
    private double getDistZ(Point3d aPt1, Point3d aPt2) {
        return Math.abs(aPt2.z-aPt1.z);
    } //koniec getDistZ
    
     private void addTrojkat(ArrayList<Tri> aTriAL, Point3d pA, Point3d pB, Point3d pC) {
        //Spr. czy zaden z punktow nie ma jakies wsp. w nieskonczonosci
        if (pA.getX()!=TDaneWej.MAX_VAL && pA.getY()!=TDaneWej.MAX_VAL && pA.getZ()!=TDaneWej.MAX_VAL &&
            pB.getX()!=TDaneWej.MAX_VAL && pB.getY()!=TDaneWej.MAX_VAL && pB.getZ()!=TDaneWej.MAX_VAL &&
            pC.getX()!=TDaneWej.MAX_VAL && pC.getY()!=TDaneWej.MAX_VAL && pC.getZ()!=TDaneWej.MAX_VAL)
            aTriAL.add(new Tri(pA, pB, pC));
    } //koniec addTrojkat
} //koniec TrojkatyR

